1、添加依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.4.0</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.40</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.12</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>4.2.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.8.13</version>
</dependency>
2、xml文件配置
spring.xml
<import resource="spring-dao.xml" />
<context:component-scan base-package="com.team5101" />
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
<property name="securityManager" ref="securityManager"/>
<property name="loginUrl" value="login.html" />
<property name="unauthorizedUrl" value="403.html"/>
<property name="filterChainDefinitions">
<value>
/login.html = anon
/subLogin = anon
/testRole = roles["admin"]
/testRole1 = roles["admin","admin1"]
/testPerms = perms["user:delete"]
/testPerms1 = perms["user:delete","user:update"]
/* = authc
</value>
</property>
</bean>
<!--创建SecurityManager对象-->
<bean class="org.apache.shiro.web.mgt.DefaultWebSecurityManager" id="securityManager">
<property name="realm" ref="realm"/>
</bean>
<bean class="com.team5101.shiro.realm.CustomRealm" id="realm">
<property name="credentialsMatcher" ref="credentialsMatcher" />
</bean>
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"
id="credentialsMatcher">
<property name="hashAlgorithmName" value="md5" />
<property name="hashIterations" value="1" />
</bean>
sping-dao.xml
<context:property-placeholder location="classpath:db.properties"/>
<bean class="com.alibaba.druid.pool.DruidDataSource" id="dataSource">
<property name="url" value="${jdbc.url}" />
<property name="username" value="${jdbc.username}" />
<property name="password" value="${jdbc.password}" />
</bean>
<bean class="org.springframework.jdbc.core.JdbcTemplate" id="jdbcTemplate">
<property name="dataSource" ref="dataSource" />
</bean>
sping-mvc.xml
<!--指定需要扫描的包,Controller注解的类" -->
<context:component-scan
base-package="com.team5101.controller" />
<!--加载注解驱动 -->
<mvc:annotation-driven />
<mvc:resources mapping="/*" location="/" />
<aop:config proxy-target-class="true" />
<bean class="org.apache.shiro.spring.LifecycleBeanPostProcessor" />
<bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
<property name="securityManager" ref="securityManager" />
</bean>
3、自定义releam
public class CustomRealm extends AuthorizingRealm {
@Resource
private UserDao userDao;
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//1.从主体传过来的认证信息中,获取用户名
String userName = (String) principalCollection.getPrimaryPrincipal();
//2.从数据库和缓存中获取角色数据
Set<String> roles = getRolesByUserName(userName);
Set<String> permissions = getPermissionsByUserName(userName);
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.setStringPermissions(permissions);
simpleAuthorizationInfo.setRoles(roles);
return simpleAuthorizationInfo;
}
private Set<String> getPermissionsByUserName(String userName) {
Set<String> sets = new HashSet<>();
sets.add("user:delete");
sets.add("user:add");
return sets;
}
private Set<String> getRolesByUserName(String userName) {
List<String> list = userDao.queryRolesByUserName(userName);
Set<String> sets = new HashSet<>(list);
return sets;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
//1.从主体传过来的认证信息中,获取用户名
String userName = (String) authenticationToken.getPrincipal();
//2.通过用户名到数据库中获取凭证
String password = getPasswordByUserName(userName);
if(password==null){
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(userName,password,"customRealm");
authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(userName));
return authenticationInfo;
}
/**
* 模拟数据库查询凭证
* @param userName
* @return
*/
private String getPasswordByUserName(String userName) {
User user = userDao.getUserByUserName(userName);
if(user!=null){
return user.getPassword();
}
return null;
}
}
4、pojo类
并添加对应的get、set方法
5、dao层
public interface UserDao {
User getUserByUserName(String userName);
List<String> queryRolesByUserName(String userName);
}
对应接口实现类
@Component
public class UserDaoImpl implements UserDao {
@Resource
private JdbcTemplate jdbcTemplate;
@Override
public User getUserByUserName(String userName) {
String sql = "select username,password from users where username = ?";
List<User> list = jdbcTemplate.query(sql, new String[]{userName}, new RowMapper<User>() {
@Override
public User mapRow(ResultSet resultSet, int i) throws SQLException {
User user = new User();
user.setUsername(resultSet.getString("username"));
user.setPassword(resultSet.getString("password"));
return user;
}
});
if(CollectionUtils.isEmpty(list)){
return null;
}
return list.get(0);
}
@Override
public List<String> queryRolesByUserName(String userName) {
String sql = "select role_name from user_roles where username = ?";
return jdbcTemplate.query(sql, new String[]{userName}, new RowMapper<String>() {
@Override
public String mapRow(ResultSet resultSet, int i) throws SQLException {
return resultSet.getString("role_name");
}
});
}
}
6、controller层
@Controller
public class UserController {
@RequestMapping(value = "/subLogin",method = RequestMethod.POST,
produces = "application/json;charset=utf-8")
@ResponseBody
public String subLogin(User user){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(),
user.getPassword());
try {
subject.login(token);
} catch (AuthenticationException e) {
return e.getMessage();
}
if(subject.hasRole("admin")){
return "有admin权限";
}
return "无admin权限";
}
}
7、数据库设计
User表
User_roles表
8、显示效果
账号密码输入正确
账号密码输入错误,显示认证失败的错误。