导入依赖
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-web</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.9</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.0.6.RELEASE</version>
</dependency>
Spring-Context配置相应Bean
<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 <!--anon的代表是不要认证的-->
/subLogin = anon
/* = authc <!--anon的代表是要认证的,一般放最后-->
</value>
</property>
</bean>
<!--创建SecurityManager-->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
<property name="realm" ref="realm" />
</bean>
<bean id="realm" class="com.ay.shiro.realm.CustomRealm">
<!-- <property name="credentialsMatcher" ref="credentialsMatcher"/> -->
</bean>
<!--<bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<property name="hashAlgorithmName" value="md5" />
<property name="hashIterations" value="1" />
</bean>-->
密码如果使用MD5加密需要credentialsMatcher
自定义Realm
一般 user,role,permission是存在数据库的3+2表,自定义Realm通过持久层读取相关需要验证的信息。
public class CustomRealm extends AuthorizingRealm {
{
super.setName("customRealm");
}
@Resource
private UserDao userDao;
@Override //授权
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String username = (String) principalCollection.getPrimaryPrincipal();
//模拟获取roles permission
Set<String> roles = getRolesByUsername(username);
Set<String> permission = getPermissionByUsername(username);
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
simpleAuthorizationInfo.setRoles(roles);
simpleAuthorizationInfo.setStringPermissions(permission);
return simpleAuthorizationInfo;
}
private Set<String> getPermissionByUsername(String username) {
List<String> permission = userDao.getPermissionByUsername(username);
if(permission == null){
return null;
}
Set<String> set = new HashSet<>(permission);
return set;
}
private Set<String> getRolesByUsername(String username) {
List<String> roles = userDao.getRolesByUsername(username);
if(roles == null){
return null;
}
Set<String> set = new HashSet<>(roles);
return set;
}
@Override //认证 主体提交认证后的处理
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String username = (String) authenticationToken.getPrincipal();
//模拟从数据库获取密码
String password = getPasswordByUsername(username);
if(password == null){
return null;
}
SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
username,password,"customRealm");
//对原密码要进行加盐,数据库存的也是要进行加盐加密的密码
authenticationInfo.setCredentialsSalt(ByteSource.Util.bytes(username));
return authenticationInfo;
}
private String getPasswordByUsername(String username) {
User user = userDao.getUserByUsername(username);
if(user != null){
return user.getPassword();
}
return null;
}
public static void main(String[] args){
Md5Hash md5Hash = new Md5Hash("123456","Ay");
System.out.println(md5Hash.toString());
}
}
控制层
得到主体,生成token,进行认证和授权。
@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);
// subject.checkRole("admin");
// subject.checkPermission("user:select");
}catch (Exception e){
return e.getMessage();
}
return "登录成功";
}
通过注释进行授权
<!--shiro注释-->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
</dependency>
bean配置
<!--开启shiro注释-->
<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>
示例方法
已认证的用户需要admin才能访问
@RequiresRoles("admin")
@RequestMapping(value = "/testRole",method = RequestMethod.GET)
@ResponseBody
public String testRole(){
return "testRole success";
}